import { useFocusObject } from '@/utils/useFocusObject'
import {
  Box3,
  BufferAttribute,
  BufferGeometry,
  CanvasTexture,
  CatmullRomCurve3,
  DoubleSide,
  Group,
  Mesh,
  MeshBasicMaterial,
  MeshPhongMaterial,
  Object3D,
  RepeatWrapping,
  Vector3
} from 'three'
import { TunnelGeometry } from '@/utils/TunnelGeometry.js'
import { useViewportStore } from '@/store/viewport'
import { storeToRefs } from 'pinia'
import { useActiveObject } from '@/store/activeObject'
import { createVNode, nextTick, render, type Ref } from 'vue'
import { Operation } from 'three-bvh-csg'
import { CSS2DObject } from 'three/examples/jsm/Addons'
import BBox from '@/components/b-box.vue'
import BTunnel from '@/components/b-tunnel.vue'
import Delaunator from 'delaunator'
import { getAreaIdByTunnelId, getAreaList } from '@/api/road'
const BASE_URL = import.meta.env.BASE_URL
export interface Coordinates extends Vector3 {
  _dragClass?: string
}
// 巷道
export interface Roadway {
  name: string
  coordinates: Coordinates[]
  closed: boolean
}
// 操作类型
export type OperationType = 'add' | 'edit'
// 设备类型
export type EquipmentType = 'video' | 'sensor' | 'baseStation'
// 设备
export interface Equipment {
  name: string
  equipmentType: EquipmentType
  equipmentId: string
  coordinates: Vector3
}
const { focusObject } = useFocusObject()
export const useAddTools = () => {
  const activeObjectStore = useActiveObject()
  const { activeShallowRef }: { activeShallowRef: Ref<Object3D> } = storeToRefs(activeObjectStore)
  const viewportStore = useViewportStore()
  const { publicGroup } = storeToRefs(viewportStore)

  let baseInfo
  // 修改中心点位置
  function updateCenterPoint (mesh: Mesh) {
    mesh.geometry.computeBoundingBox()
    const box3 = new Box3()
    box3.expandByObject(mesh)
    const center = new Vector3(0)
    box3.getCenter(center)
    mesh.position.copy(center)
    mesh.geometry.center()
  }
  // 名字为name的分组时否存在，不存在就创建并加入 publicGroup
  function hasGroup (name: string, created = true) {
    if (!publicGroup.value) return
    let group = publicGroup.value?.children.find((item) => item.name === name)
    if (!group && created) {
      group = new Group()
      group.name = name
      publicGroup.value?.add(group)
    }
    return group
  }
  // 收缩坐标的位数，节约性能
  function $zoomCoordinate (coordinate: Vector3) {
    return new Vector3(coordinate.x, coordinate.y, coordinate.z)
    // return new Vector3(
    //   coordinate.x - baseInfo.xDrawString,
    //   coordinate.y,
    //   coordinate.z - baseInfo.zDrawString
    // )
  }
  // 新增巷道
  function addRoadway (type: OperationType, data: Roadway, closed: boolean) {
    // 创建mesh
    const vecs = data.coordinates.map((item) => {
      return $zoomCoordinate(item)
    })

    const path = new CatmullRomCurve3(vecs)
    const geometry = new TunnelGeometry(path, TunnelGeometry.pathToUMapping(path, 3, 0.3), closed)
    let material = new MeshPhongMaterial({ color: 0xffffff, side: DoubleSide })
    let userData = {
      type: 'roadway',
      tunnelId: data.tunnelId,
      customData: {}
    }
    if (type === 'edit') {
      material = activeShallowRef.value.material.clone()
      userData = {
        ...activeShallowRef.value.userData
      }
    }
    const tube = new Operation(geometry, material)
    tube.userData = userData
    tube.name = data.name
    // 修改中心点
    updateCenterPoint(tube)

    const group = hasGroup('巷道')
    group.add(tube)
    // 加入场景，通知相关控件
    if (type === 'edit') {
      const Object3D = activeShallowRef.value
      activeObjectStore.setActiveVO(undefined)
      Object3D?.parent?.remove(Object3D)
    }
    activeObjectStore.setActiveVO(tube)
    publicGroup.value?.add(group)
  }
  // 将导线数据生成巷道后加入场景
  function loadWireToScene (data: WireData) {
    baseInfo = data.baseInfo
    data.wireItems.forEach((item) => {
      addRoadway(
        'add',
        {
          name: item.tunnelName,
          tunnelId: item.tunnelId,
          coordinates: item.pointVos
        },
        false
      )
    })
    nextTick(() => {
      const group = hasGroup('巷道')
      if (group) {
        focusObject(group)
      }
    })
  }
  // 创建CSS2D节点
  function createdLabel (item) {
    const container = document.createElement('div')
    const vm = createVNode(BBox, {
      name: item.name,
      id: item.uuid,
      detailDtos: item.userData.detailDtos
    }, null)
    render(vm, container)
    const label = new CSS2DObject(container.firstElementChild as Node)
    label.Vnode = vm
    return label
  }
  // 删除CSS2D节点
  function deleteLabel (name: string) {
    const css2DRendererDiv = document.getElementsByClassName('css2DRenderer')[0]
    for (let i = css2DRendererDiv.children.length - 1; i >= 0; i--) {
      if (css2DRendererDiv.children[i].textContent === name) {
        css2DRendererDiv.removeChild(css2DRendererDiv.children[i])
      }
    }
  }

  async function createWorkFaces (node) {
    const group1 = hasGroup('工作面')
    const points = node.children.map(item => item.geometry.parameters.path.points).flat()
    // 2. Delaunay 三角剖分（转换为二维坐标）
    const delaunayPoints = points.map(p => [p.x, p.y]);
    const delaunay = Delaunator.from(delaunayPoints);
    const triangles = delaunay.triangles; // 获得三角形索引数组
    // 3. 创建几何体并设置顶点
    const geometry = new BufferGeometry();
    const positions = new Float32Array(points.length * 3);
    points.forEach((p, i) => {
      positions[i * 3] = p.x;
      positions[i * 3 + 1] = p.y;
      positions[i * 3 + 2] = p.z;
    });
    geometry.setAttribute('position', new BufferAttribute(positions, 3));
    // 4. 设置三角形索引
    geometry.setIndex([...triangles]);
    // 5. 计算法线（用于光照）
    geometry.computeVertexNormals();
    // 6. 计算 UV 映射
    const positions1 = geometry.attributes.position.array;
    let sumX = 0, sumZ = 0;
    const points1 = [];
    // 转换为二维点集并计算均值
    for (let i = 0; i < positions1.length; i += 3) {
      const x = positions1[i];
      const z = positions1[i + 2];
      points1.push([x, z]);
      sumX += x;
      sumZ += z;
    }
    const meanX = sumX / (positions1.length / 3);
    const meanZ = sumZ / (positions1.length / 3);
    // 计算协方差矩阵
    let covXX = 0, covXZ = 0, covZZ = 0;
    for (const [x, z] of points1) {
      const dx = x - meanX;
      const dz = z - meanZ;
      covXX += dx * dx;
      covXZ += dx * dz;
      covZZ += dz * dz;
    }
    const total = points1.length;
    covXX /= total;
    covXZ /= total;
    covZZ /= total;
    // 协方差矩阵的特征值分解
    const a = covXX;
    const b = covXZ;
    const c = covZZ;
    // 特征值计算
    const trace = a + c;
    const det = a * c - b * b;
    const discriminant = Math.sqrt(trace * trace / 4 - det);
    const lambda1 = trace / 2 + discriminant;
    // 主方向特征向量（第一主成分）
    const angle = Math.atan2(lambda1 - a, b);
    const dirX = Math.cos(angle);
    const dirZ = Math.sin(angle);
    // 计算所有顶点在主方向上的投影范围
    let minProj = Infinity;
    let maxProj = -Infinity;
    const projections = [];
    for (const [x, z] of points1) {
      const proj = (x - meanX) * dirX + (z - meanZ) * dirZ;
      projections.push(proj);
      minProj = Math.min(minProj, proj);
      maxProj = Math.max(maxProj, proj);
    }
    // 计算副方向（垂直于主方向）
    const perpDirX = -dirZ;
    const perpDirZ = dirX;
    // 副方向投影范围
    let minPerp = Infinity;
    let maxPerp = -Infinity;
    for (const [x, z] of points1) {
      const proj = (x - meanX) * perpDirX + (z - meanZ) * perpDirZ;
      minPerp = Math.min(minPerp, proj);
      maxPerp = Math.max(maxPerp, proj);
    }
    // 生成 UV 坐标
    const uvs = new Float32Array(points1.length * 2);
    for (let i = 0; i < points1.length; i++) {
      const [x, z] = points1[i];
      // 主方向投影
      const projMain = projections[i];
      const u = (projMain - minProj) / (maxProj - minProj);
      // 副方向投影
      const projPerp = (x - meanX) * perpDirX + (z - meanZ) * perpDirZ;
      const v = (projPerp - minPerp) / (maxPerp - minPerp);

      uvs[i * 2] = u;
      uvs[i * 2 + 1] = 1 - v; // 翻转 V 轴
    }
    geometry.setAttribute('uv', new BufferAttribute(uvs, 2));
    // 1. 创建 Canvas 并绘制文字
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const text = node.name;
    // 设置 Canvas 尺寸（建议为 2 的幂次方）
    canvas.width = 512;
    canvas.height = 256;
    // 绘制背景和文字
    const { data: areaId } = await getAreaIdByTunnelId(node.children[0].uuid)
    const { data } = await getAreaList({ areaId })
    const progress = (data[0].accruedAllFootage / data[0].designLen).toFixed(2)
    // 填充渐变：
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.font = '40px Arial';
    ctx.fillStyle = '#00ffa7';
    ctx.textAlign = 'center';

    const img = new Image();
    img.src = BASE_URL + 'materials/goaf.jpg';
    const img1 = new Image();
    img1.src = BASE_URL + 'materials/Unmined.jpg';
    img1.onload = function () {
      const x = progress * 512
      ctx.drawImage(img, 0, 0, 512, 256);
      ctx.drawImage(img1, x - 10, 0, 512, 256, x - 10, 0, 512, 256);
      ctx.fillText(text, canvas.width / 2, canvas.height / 2);
      const texture = new CanvasTexture(canvas);
      const material = new MeshBasicMaterial({
        map: texture,
        side: DoubleSide,
        transparent: true,
        opacity: 0.5,
      });
      // 7. 创建网格并添加到场景
      const mesh = new Mesh(geometry, material);
      mesh.name = node.name
      mesh.uuid = node.children[0].uuid
      updateCenterPoint(mesh)
      if (group1) {
        group1.add(mesh)
      }
    }
  }

  function createdTunnelLabel (item) {
    const container = document.createElement('div')
    const vm = createVNode(BTunnel, {
      info: item,
    }, null)
    render(vm, container)
    const label = new CSS2DObject(container.firstElementChild as Node)
    label.Vnode = vm
    return label
  }

  return {
    hasGroup,
    addRoadway,
    loadWireToScene,
    updateCenterPoint,
    createdLabel,
    deleteLabel,
    createWorkFaces,
    createdTunnelLabel
  }
}
